package com.bio.jsf.util;

import com.bio.jpa.entities.GenBank;
import com.bio.jpa.session.GenBankFacade;
import com.bio.tests.GenBankParser;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.ejb.EJB;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(asyncSupported = true, name = "DownloadServlet",
urlPatterns = {"/download"},
initParams = {
    @WebInitParam(name = "param1", value = "value1"),
    @WebInitParam(name = "param2", value = "value2")})
@Named(value = "DownloadServlet")
public class DownloadServlet extends HttpServlet {

    @EJB
    private GenBankFacade gbfacade;
    @Inject
    private GenBankParser gbp;

    public DownloadServlet() {
    }

    public DownloadServlet(GenBankFacade gbfacade, GenBankParser gbp) {
        this.gbfacade = gbfacade;
        this.gbp = gbp;
    }

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String id = req.getParameter("id");
        if (id == null) {
            resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
        }
        GenBank gb = gbfacade.find(Integer.parseInt(id));
        File fgb = gbp.exportToFile(gb);
        if (fgb == null) {
            resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
        }
        File info = null;
        if (gb != null) {
            info = new File(gbp.getInfo(gb));
        }
        List<File> filesToSend = new ArrayList<File>();
        filesToSend.add(fgb);
        filesToSend.add(info);

        doGetZip(req, resp, filesToSend, id);

    }

    protected void doGetZip(HttpServletRequest request, HttpServletResponse response, List<File> list, String id) throws ServletException, IOException {
        try {
            //
            // Checks to see if the directory contains some files.
            //
            if (list != null && list.size() > 0) {
                //
                // Call the zipFiles method for creating a zip stream.
                //
                byte[] zip = zipFiles(list);
                //
                // Sends the response back to the user / browser. The
                // content for zip file type is "application/zip". We
                // also set the content disposition as attachment for
                // the browser to show a dialog that will let user 
                // choose what action will he do to the sent content.
                //
                response.setContentType("application/zip");
                response.setHeader("Content-Disposition", "attachment; filename=\"" + id + ".zip\"");
                response.setContentLength((int) zip.length);
                ServletOutputStream sos = response.getOutputStream();
                if (sos != null && zip != null) {
                    sos.write(zip);
                    sos.flush();
                    sos.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private byte[] zipFiles(List<File> files) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ZipOutputStream zos = new ZipOutputStream(baos);
        zos.setMethod(ZipOutputStream.DEFLATED);
        zos.setLevel(Deflater.BEST_SPEED);
        byte bytes[] = new byte[2048];
        for (File file : files) {
            FileInputStream fis = new FileInputStream(file);
            BufferedInputStream bis = new BufferedInputStream(fis);
            ZipEntry ze = new ZipEntry(file.getName());
            zos.putNextEntry(ze);
            int bytesRead;
            while ((bytesRead = bis.read(bytes)) != -1) {
                zos.write(bytes, 0, bytesRead);
            }
            zos.closeEntry();
            bis.close();
            fis.close();
            file.delete();
        }
        files.clear();
        zos.flush();
        baos.flush();
        zos.close();
        baos.close();

        return baos.toByteArray();
    }
}
